package cc.rengu.igas.opms.core.service.trans.gateway;

import cc.rengu.igas.momp.facade.base.Header;
import cc.rengu.igas.momp.facade.bean.PaymentOrderCouponInfoBean;
import cc.rengu.igas.momp.facade.bean.PaymentOrderDetailBean;
import cc.rengu.igas.momp.facade.request.ComboPaymentRequest;
import cc.rengu.igas.momp.facade.request.ComboPaymentReversalRequest;
import cc.rengu.igas.momp.facade.response.ComboPaymentResponse;
import cc.rengu.igas.momp.facade.result.Result;
import cc.rengu.igas.opms.common.constant.OpmsTreeNodeConstant;
import cc.rengu.igas.opms.common.constant.OpmsParamConstant;
import cc.rengu.igas.share.common.constant.TransCacheConstant;
import cc.rengu.igas.share.core.model.MchntInfo;
import cc.rengu.igas.share.core.realize.MchntService;
import cc.rengu.igas.share.core.realize.impl.MchntServiceImpl;
import cc.rengu.oltp.service.common.enums.*;
import cc.rengu.igas.opms.common.enums.RespCodeEnum;
import cc.rengu.igas.opms.core.service.base.PayService;
import cc.rengu.igas.opms.facade.bean.EncryptAssInfo;
import cc.rengu.igas.opms.facade.request.CupsGatewayPayRequest;
import cc.rengu.igas.opms.facade.response.CupsGatewayPayResponse;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.entity.*;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.model.OrderInfo;
import cc.rengu.oltp.service.realize.DubboService;
import cc.rengu.oltp.service.realize.OrderService;
import cc.rengu.oltp.service.realize.SysParamService;
import cc.rengu.oltp.service.realize.impl.DubboServiceImpl;
import cc.rengu.oltp.service.realize.impl.OrderServiceImpl;
import cc.rengu.oltp.service.realize.impl.SysParamServiceImpl;
import cc.rengu.oltp.utility.util.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 银联新网银支付
 */
public class UpgwPayService extends PayService {

    @Override
    protected Object bizBeforeCust() throws Exception {
        CupsGatewayPayRequest cupsGatewayPayRequest = new CupsGatewayPayRequest();
        ConvertUtil.convertOutput(cupsGatewayPayRequest);
        return cupsGatewayPayRequest;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {

        CupsGatewayPayRequest cupsGatewayPayRequest = (CupsGatewayPayRequest) request;
        String instId = cupsGatewayPayRequest.getHeader().getInstId();
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        List<ChannelCallCfg> mompTxnNumList = txnInfo.getChannelCallCfgList().stream().filter(channelCallCfg -> ChannelEnum.MOMP.getChannelType().equals(channelCallCfg.getCallChannelId())).collect(Collectors.toList());

        //校验订单信息
        OrderService orderService = new OrderServiceImpl();
        OrderInfo orderInfo = orderService.selectOrderInfoByUserOrderId(instId, cupsGatewayPayRequest.getUserOrderId());
        if (null == orderInfo) {
            rglog.error("订单信息不存在!");
            throw new BizException(RespCodeEnum.ORDER_NOEXIT.getRespCode(), RespCodeEnum.ORDER_NOEXIT.getRespDesc());
        }
        UserOrderInfo userOrderInfo = orderInfo.getUserOrderInfo();
        List<MchntOrderInfo> mchntOrderInfoList = orderInfo.getMchntOrderInfoList();

        //购买卡券的不支持使用优惠券
        boolean isCouponTrans = null != cupsGatewayPayRequest.getCouponInfo() && !StringUtil.isEmptyOrNull(cupsGatewayPayRequest.getCouponInfo().getDiscountId());
        boolean isBuyCouponTrans = false;
        if ("00".equals(mchntOrderInfoList.get(0).getBizSceneType()) || "02".equals(mchntOrderInfoList.get(0).getBizSceneType())) {
            isBuyCouponTrans = true;
        }
        if (isCouponTrans && isBuyCouponTrans) {
            rglog.info("购买卡券的交易不支持使用优惠券");
            throw new BizException(RespCodeEnum.NOT_SURP_TRANS_TYPE_ERROR.getRespCode(), RespCodeEnum.NOT_SURP_TRANS_TYPE_ERROR.getRespDesc());
        }

        //转换商户订单
        convertMchntOrder(mchntOrderInfoList, userOrderInfo, cupsGatewayPayRequest, isCouponTrans, isBuyCouponTrans);

        //调用营销获取优惠
        if (!isBuyCouponTrans) {
            PayOrderInfo mompPayOrderInfo = registMompOrderInfo(userOrderInfo, mompTxnNumList.get(0));
            if (null == mompPayOrderInfo) {
                updateOrderFail(userOrderInfo, mchntOrderInfoList, null);
                throw new BizException(RespCodeEnum.INSERT_PAY_ORDER_ERROR.getRespCode(), RespCodeEnum.INSERT_PAY_ORDER_ERROR.getRespDesc());
            }
            xmlTreeUtil.setXmlTreeObjectValue(OpmsTreeNodeConstant.PAY_ORDER_INFO, mompPayOrderInfo);
            Result<ComboPaymentResponse> comboPaymentResponseResult = callMompPayServcie(cupsGatewayPayRequest, mompTxnNumList.get(0), isCouponTrans, userOrderInfo, mchntOrderInfoList);
            //解析营销调用结果
            analysisMompResult(userOrderInfo, mchntOrderInfoList, mompPayOrderInfo, comboPaymentResponseResult, mompTxnNumList.get(1), isCouponTrans, cupsGatewayPayRequest);
        }

        //登记网关支付订单信息
        PayOrderInfo payOrderInfo = registPayOrderInfo(cupsGatewayPayRequest, userOrderInfo);
        if (null == payOrderInfo) {
            updateOrderFail(userOrderInfo, mchntOrderInfoList, null);
            mompRevsal(mompTxnNumList.get(1));
            throw new BizException(RespCodeEnum.INSERT_PAY_ORDER_ERROR.getRespCode(), RespCodeEnum.INSERT_PAY_ORDER_ERROR.getRespDesc());
        }

        //区分个人网银和企业网银分别调用ESB获取网银转发报文
        rglog.debug("根据业务种类:<{}>,区分个人网银还是企业网银", cupsGatewayPayRequest.getHeader().getBizType());
        if ("00".equals(cupsGatewayPayRequest.getHeader().getBizType())) {

        } else if ("01".equals(cupsGatewayPayRequest.getHeader().getBizType())) {

        } else {
            rglog.info("不识别的业务类型:<{}>", cupsGatewayPayRequest.getHeader().getBizType());
            updateOrderFail(userOrderInfo, mchntOrderInfoList, null);
            mompRevsal(mompTxnNumList.get(1));
            throw new BizException(RespCodeEnum.PARAM_ERROR.getRespCode(), RespCodeEnum.PARAM_ERROR.getRespDesc());
        }

        //获取网关支付应答报文
        CupsGatewayPayResponse cupsGatewayPayResponse = new CupsGatewayPayResponse();

        //辅助加密信息
        EncryptAssInfo encryptAssInfo = new EncryptAssInfo();


        //组响应信息
        BizResponse<CupsGatewayPayResponse> bizResponse = new BizResponse<>();
        bizResponse.setRspSysId(AppParamConstant.IGAS);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        return null;
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        CupsGatewayPayResponse cupsGatewayPayResponse = (CupsGatewayPayResponse) bizResponse.getResult();
        ConvertUtil.convertInput(cupsGatewayPayResponse);
    }

    /**
     * 营销冲销
     *
     * @param channelCallCfg 营销冲销通道服务调用配置
     * @throws Exception 异常
     */
    private void mompRevsal(ChannelCallCfg channelCallCfg) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        ComboPaymentRequest comboPaymentRequest = (ComboPaymentRequest) xmlTreeUtil.getXmlTreeObjectValue("comboPaymentRequest", ComboPaymentRequest.class);
        Header header = comboPaymentRequest.getHeader();
        ComboPaymentReversalRequest comboPaymentRevsalRequest = new ComboPaymentReversalRequest();
        comboPaymentRevsalRequest.setOrigTraceNo(header.getTraceNo());
        header.setTxnNum(channelCallCfg.getCallChannelTxn());
        header.setTraceNo(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + channelCallCfg.getCallIndex());
        comboPaymentRevsalRequest.setHeader(header);
        DubboServiceImpl dubboService = new DubboServiceImpl();
        int iReturnCode = dubboService.asynCallDubboService(OpmsParamConstant.DUBBO_MOMP_PAYMENT_SERVICE, "comboPaymentRevsal", comboPaymentRevsalRequest, "AsynComboPaymentRevsalService");
        if (iReturnCode != 0) {
            rglog.warn("异步营销冲正服务注册失败！");
        }
    }

    /**
     * 购买卡券的交易商户订单表 校验交易权限/商户限额/商户订单初始化
     *
     * @param mchntOrderInfoList 商户订单
     * @param userOrderInfo      用户订单
     * @param request            支付请求
     * @throws Exception 异常
     */
    private void convertMchntOrder(List<MchntOrderInfo> mchntOrderInfoList, UserOrderInfo userOrderInfo, CupsGatewayPayRequest request,
                                   boolean isCouponTrans, boolean isBuyCouponTrans) throws Exception {

        //商户订单初始化
        MchntService mchntService = new MchntServiceImpl();
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        boolean surpCreditAcct = true;
        boolean surpDebitAcct = true;
        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {

            //获取交易的商户号
            String transMchntNo;
            if (isBuyCouponTrans) {
                transMchntNo = userOrderInfo.getGroupMchntNo();
            } else {
                transMchntNo = mchntOrderInfo.getMchntNo();
            }

            /*卡券购买交易，不计算商户手续费，只需检查一次商户权限，商户号取自用户订单表*/
            MchntInfo mchntInfo = mchntService.getMchntInfo(request.getHeader().getInstId(), transMchntNo);
            if (null == mchntInfo) {
                rglog.error("查询商户基本信息失败<{}>", transMchntNo);
                throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
            }
            /*交易权限检查*/
            boolean checkResult = mchntService.checkMchntAuth(request.getHeader().getInstId(), transMchntNo, null, request.getHeader().getTxnNum(), request.getHeader().getBizType(), AcctTypeEnum.ALL.getAcctType());
            if (!checkResult) {
                rglog.error("商户<{}>无此交易权限!", transMchntNo);
                throw new BizException(RespCodeEnum.NOT_SURP_TRANS_TYPE_ERROR.getRespCode(), RespCodeEnum.NOT_SURP_TRANS_TYPE_ERROR.getRespDesc());
            }
            /*商户限额处理,判断交易是否支持借记卡和贷记卡*/
            int limitFlag = mchntService.checkMchntTransLimit(request.getHeader().getInstId(), mchntOrderInfo.getRealSettleAmt(), LimitAcctTypeEnum.ALL, transMchntNo, null, request.getHeader().getTxnNum());
            if (2 == limitFlag) {
                throw new BizException(RespCodeEnum.MCHNT_AMT_OVER.getRespCode(), RespCodeEnum.MCHNT_AMT_OVER.getRespDesc());
            } else if (1 == limitFlag) {
                surpCreditAcct = false;
            } else if (3 == limitFlag) {
                surpDebitAcct = false;
            }

            //商户订单初始化
            mchntOrderInfo.setBizProdCode(txnInfo.getSrcTxnAuthCfg().getBizProdCode());
            mchntOrderInfo.setTxnNum(request.getHeader().getTxnNum());
            mchntOrderInfo.setBizType(request.getHeader().getBizType());
            mchntOrderInfo.setSysSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
            mchntOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
            mchntOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
            mchntOrderInfo.setMchntDiscountFee("0.00");
            mchntOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            /*判断是否独立维护资料的门店*/
            if ("11".equals(mchntInfo.getMchntType()) && AppParamConstant.NO.equals(mchntInfo.getIndependentDataFlag())) {
                mchntOrderInfo.setChainMchntNo(mchntInfo.getChainMchntNo());
            }
            //判断是否实时清算,使用优惠券的交易不实时清算
            if (isCouponTrans) {
                mchntOrderInfo.setRealSettleFlag(AppParamConstant.NO);
            } else {
                String realSettleFlag = mchntService.getRealSettleFlag(mchntInfo.getMchntNo(), txnInfo.getSrcTxnAuthCfg().getBizProdCode(), mchntOrderInfo.getBizSceneType(), mchntOrderInfo.getRealSettleAmt());
                mchntOrderInfo.setRealSettleFlag(realSettleFlag);
                if (AppParamConstant.YES.equals(mchntOrderInfo.getRealSettleFlag())) {
                    mchntOrderInfo.setRealSettleType("99");
                }
            }
        }

        /*合并订单支付，不能合并特殊费率跟非特殊费率，不能合并d0清算跟非d0清算*/
        if (mchntOrderInfoList.size() > 1) {
            List<MchntOrderInfo> mchntOrderInfoSpFeeList = mchntOrderInfoList.stream().filter(item -> "0".equals(item.getFeeInputMode())).collect(Collectors.toList());
            if (!mchntOrderInfoSpFeeList.isEmpty() && mchntOrderInfoSpFeeList.size() != mchntOrderInfoList.size()) {
                rglog.error("合并订单中存在特殊费率跟非特殊费率的订单，拒绝交易");
                throw new BizException(RespCodeEnum.ORDER_NOT_ALLOW_PAY.getRespCode(), RespCodeEnum.ORDER_NOT_ALLOW_PAY.getRespDesc());
            }
            List<MchntOrderInfo> mchntOrderInfoD0List = mchntOrderInfoList.stream().filter(item -> AppParamConstant.YES.equals(item.getRealSettleFlag())).collect(Collectors.toList());
            if (!mchntOrderInfoD0List.isEmpty() && mchntOrderInfoD0List.size() != mchntOrderInfoList.size()) {
                rglog.error("合并订单中存在d0清算跟非d0清算的订单，拒绝交易");
                throw new BizException(RespCodeEnum.ORDER_NOT_ALLOW_PAY.getRespCode(), RespCodeEnum.ORDER_NOT_ALLOW_PAY.getRespDesc());
            }
        }

        /*
         * 判断限定的账户类型
         * 借贷记卡都支持     - 00 混合账户类型
         * 支持借记不支持贷记 - 01 借记账户类型
         * 支持贷记不支持借记 - 02 贷记账户类型
         */
        if (!surpCreditAcct && !surpDebitAcct) {
            rglog.info("当前订单借贷记卡都不支持");
            throw new BizException(RespCodeEnum.MCHNT_AMT_OVER.getRespCode(), RespCodeEnum.MCHNT_AMT_OVER.getRespDesc());
        } else if (surpCreditAcct && surpDebitAcct) {
            xmlTreeUtil.setXmlTreeStringValue("LmtAcctTpCd", "00");
        } else {
            if (surpDebitAcct) {
                xmlTreeUtil.setXmlTreeStringValue("LmtAcctTpCd", "01");
            } else {
                xmlTreeUtil.setXmlTreeStringValue("LmtAcctTpCd", "02");
            }
        }
    }

    /**
     * 登记营销支付订单表
     *
     * @param userOrderInfo  用户订单
     * @param channelCallCfg 营销合并支付通道服务调用配置
     * @return 营销支付订单
     * @throws Exception 异常
     */
    private PayOrderInfo registMompOrderInfo(UserOrderInfo userOrderInfo, ChannelCallCfg channelCallCfg) throws Exception {

        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        PayOrderInfo payOrderInfo = new PayOrderInfo();
        BeanUtil.beanCopy(userOrderInfo, payOrderInfo);
        payOrderInfo.setTxnDate(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_DATE));
        payOrderInfo.setTxnTime(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_TIME));
        payOrderInfo.setBizType(channelCallCfg.getBizType());
        payOrderInfo.setTxnNum(channelCallCfg.getTxnNum());
        payOrderInfo.setRealPayAmt(userOrderInfo.getOrderAmt());
        payOrderInfo.setPayType(PayTypeEnum.OTHER.getPayType());
        payOrderInfo.setPayerAcctType(AcctTypeEnum.COUPON.getAcctType());
        payOrderInfo.setSysSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
        payOrderInfo.setMsgDstId(channelCallCfg.getCallChannelId());
        payOrderInfo.setDstTxnNum(channelCallCfg.getCallChannelTxn());
        payOrderInfo.setDstCallIndex(channelCallCfg.getCallIndex());
        payOrderInfo.setChannelSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
        payOrderInfo.setChannelReconKey(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + channelCallCfg.getCallIndex());
        payOrderInfo.setBizStatus(BizStatusEnum.INIT.getStatus());
        payOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        payOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        OrderService orderService = new OrderServiceImpl();
        if (!orderService.registerOrderInfo(null, null, payOrderInfo)) {
            rglog.warn("登记支付订单表失败,payOrderInfo=[{}]", JSON.toJSONString(payOrderInfo));
            return null;
        }

        rglog.debug("登记支付订单表成功,payOrderInfo:<{}>", JSON.toJSONString(payOrderInfo));
        return payOrderInfo;
    }

    /**
     * 更新订单为失败
     *
     * @param userOrderInfo      用户订单
     * @param mchntOrderInfoList 商户订单
     * @param payOrderInfo       支付订单
     * @throws Exception 异常信息
     */
    private void updateOrderFail(UserOrderInfo userOrderInfo, List<MchntOrderInfo> mchntOrderInfoList, PayOrderInfo payOrderInfo) throws Exception {
        OrderService orderService = new OrderServiceImpl();
        String currentDateTime = DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS");
        //更新用户订单表/商户订单表状态为失败
        userOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
        userOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
        userOrderInfo.setUpdateTime(currentDateTime);
        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
            mchntOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
            mchntOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
            mchntOrderInfo.setUpdateTime(currentDateTime);
        }
        if (null == payOrderInfo) {
            if (!orderService.updateOrderInfo(userOrderInfo, mchntOrderInfoList, null)) {
                rglog.warn("更新用户订单/商户订单信息失败");
            } else {
                rglog.debug("更新用户订单/商户订单信息成功");
            }
        } else {
            payOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
            payOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
            payOrderInfo.setUpdateTime(currentDateTime);
            if (!orderService.updateOrderInfo(userOrderInfo, mchntOrderInfoList, payOrderInfo)) {
                rglog.warn("更新用户订单/商户订单信息失败");
            } else {
                rglog.debug("更新用户订单/商户订单信息成功");
            }
        }
    }


    /**
     * 调用营销合并支付
     *
     * @param request            请求体
     * @param mompChannelCallCfg 营销合并支付通道服务调用配置
     * @param isCouponTrans      是否参与营销
     * @param userOrderInfo      用户订单
     * @param mchntOrderInfoList 商户订单
     * @return 合并支付调用结果
     * @throws Exception 异常
     */
    private Result<ComboPaymentResponse> callMompPayServcie(CupsGatewayPayRequest request, ChannelCallCfg mompChannelCallCfg, boolean isCouponTrans,
                                                            UserOrderInfo userOrderInfo, List<MchntOrderInfo> mchntOrderInfoList) throws Exception {

        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        xmlTreeUtil.setXmlTreeStringValue("discountFlag", AppParamConstant.NO);

        //获取营销产品编码,若营销产品编码未配置则判断用户是否使用卡劵未使用卡劵时交易可以继续往下进行
        SysParamService sysParamService = new SysParamServiceImpl();
        SysParam sysParam = sysParamService.getSysParamInfo(request.getHeader().getInstId(), OpmsParamConstant.MOMP_PROD_CODE,
                request.getHeader().getTxnNum() + request.getHeader().getBizType() + AcctTypeEnum.ALL.getAcctType());
        if (sysParam == null) {
            rglog.error("根据交易码<{}>、业务细分<{}>转换营销产品编码失败", request.getHeader().getTxnNum(), request.getHeader().getBizType());
            return null;
        }

        //请求头
        Header header = new Header();
        header.setInstId(request.getHeader().getInstId());
        header.setChanlId(OpmsParamConstant.OPM_SYS_ID);
        header.setSrcSysId(AppParamConstant.SYS_ID);
        header.setBizType(OpmsParamConstant.DUBBO_DEFAULT_BIZ_TYPE);
        header.setVersion("1.0.0");
        header.setTxnNum(mompChannelCallCfg.getCallChannelTxn());
        header.setTraceNo(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + mompChannelCallCfg.getCallIndex());
        header.setTransTime(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_TIME));
        header.setTransDate(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_DATE));
        //请求体
        ComboPaymentRequest comboPaymentRequest = new ComboPaymentRequest();
        ConvertUtil.convertOutput(comboPaymentRequest);
        comboPaymentRequest.setHeader(header);
        comboPaymentRequest.setUserId(xmlTreeUtil.getXmlTreeStringValue(OpmsTreeNodeConstant.USER_MOBILE_NO));
        comboPaymentRequest.setBizProdCode(sysParam.getParamValue());
        comboPaymentRequest.setMchntOrderId(request.getUserOrderId());
        comboPaymentRequest.setTransAmt(userOrderInfo.getNeedPayAmt());
        List<PaymentOrderDetailBean> orderDetailList = new ArrayList<>();
        convertOrderDetail(orderDetailList, mchntOrderInfoList);
        comboPaymentRequest.setOrderDetailList(orderDetailList);
        if (isCouponTrans) {
            List<PaymentOrderCouponInfoBean> couponInfoList = new ArrayList<>();
            PaymentOrderCouponInfoBean paymentOrderCouponInfoBean = new PaymentOrderCouponInfoBean();
            paymentOrderCouponInfoBean.setCouponNo(request.getCouponInfo().getDiscountId());
            couponInfoList.add(paymentOrderCouponInfoBean);
            comboPaymentRequest.setCouponInfoList(couponInfoList);
        }
        xmlTreeUtil.setXmlTreeObjectValue("comboPaymentRequest", comboPaymentRequest);
        rglog.debug("营销优惠试算请求:<{}>", JSON.toJSONString(comboPaymentRequest));

        /*调用营销接口进行优惠试算*/
        try {
            DubboService dubboService = new DubboServiceImpl();
            return (Result<ComboPaymentResponse>) dubboService.callDubboService(OpmsParamConstant.DUBBO_MOMP_PAYMENT_SERVICE, "comboPayment", comboPaymentRequest);
        } catch (Exception e) {
            rglog.error("调用营销合并支付接口异常:<{}>", e);
            return null;
        }
    }

    /**
     * 转换营销的订单详情
     *
     * @param orderDetailList    营销订单详情
     * @param mchntOrderInfoList 商户订单表
     */
    void convertOrderDetail(List<PaymentOrderDetailBean> orderDetailList, List<MchntOrderInfo> mchntOrderInfoList) {
        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
            PaymentOrderDetailBean paymentOrderDetailBean = new PaymentOrderDetailBean();
            paymentOrderDetailBean.setMchntNo(mchntOrderInfo.getMchntNo());
            if (mchntOrderInfo.getOrderDiscountAmt() != null && !mchntOrderInfo.getOrderDiscountAmt().isEmpty()) {
                paymentOrderDetailBean.setOrderAmt(AmountUtil.subtraction(mchntOrderInfo.getOrderAmt(), mchntOrderInfo.getOrderDiscountAmt()));
            } else {
                paymentOrderDetailBean.setOrderAmt(mchntOrderInfo.getOrderAmt());
            }
            paymentOrderDetailBean.setFeeInputMode(mchntOrderInfo.getFeeInputMode());
            paymentOrderDetailBean.setMchntFeeReceivableRate(mchntOrderInfo.getFeeRate());
            paymentOrderDetailBean.setMchntSettleAmt(mchntOrderInfo.getRealSettleAmt());
            paymentOrderDetailBean.setMchntFeeReceivable(mchntOrderInfo.getMchntFee());
            orderDetailList.add(paymentOrderDetailBean);
        }
    }

    /**
     * 解析营销合并支付调用结果
     *
     * @param userOrderInfo      用户订单表
     * @param mchntOrderInfoList 商户订单表
     * @param mompPayOrderInfo   营销支付订单表
     * @param mompResult         营销合并支付调用结果
     * @param channelCallCfg     通道服务调用配置
     * @param isCouponTrans      是否使用优惠劵
     * @throws Exception 异常
     */
    private void analysisMompResult(UserOrderInfo userOrderInfo, List<MchntOrderInfo> mchntOrderInfoList, PayOrderInfo mompPayOrderInfo, Result<ComboPaymentResponse> mompResult,
                                    ChannelCallCfg channelCallCfg, boolean isCouponTrans, CupsGatewayPayRequest cupsGatewayPayRequest) throws Exception {
        String discountFlag = "N";
        String feeDiscountFlag = "N";
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        OrderService orderService = new OrderServiceImpl();

        if (null == mompResult || !mompResult.isSuccess()) {
            if (isCouponTrans) {
                rglog.warn("使用卡劵交易调用营销失败,整个交易失败");
                updateOrderFail(userOrderInfo, mchntOrderInfoList, mompPayOrderInfo);
                throw new BizException(RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
            } else {
                mompPayOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                mompPayOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                mompPayOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                if (!orderService.updateOrderInfo(null, null, mompPayOrderInfo)) {
                    rglog.warn("更新用户订单/商户订单信息失败");
                }
                rglog.debug("交易调用营销失败但未使用卡劵可继续进行交易");
                /*d0实时入账手续费四舍五入处理*/
                if (AppParamConstant.YES.equals(mchntOrderInfoList.get(0).getRealSettleFlag())) {
                    for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                        mchntOrderInfo.setMchntDiscountFee("0.00");
                        mchntOrderInfo.setRealMchntFee(AmountUtil.rounding(mchntOrderInfo.getRealMchntFee(), 2));
                        mchntOrderInfo.setMchntFee(AmountUtil.rounding(mchntOrderInfo.getMchntFee(), 2));
                        mchntOrderInfo.setMchntSettleAmt(AmountUtil.subtraction(mchntOrderInfo.getRealSettleAmt(), mchntOrderInfo.getRealMchntFee()));
                    }
                }
                return;
            }
        }

        ComboPaymentResponse mompResponse = mompResult.getResult();
        //营销调用超时，向营销系统异步发起冲正
        if (OpmsParamConstant.DUBBO_OVERTIME.equals(mompResponse.getRespCode())) {
            rglog.info("营销试算DUBBO接口-调用超时，发起冲正");
            mompRevsal(channelCallCfg);
            //更新用户订单表/商户订单表状态为失败
            updateOrderFail(userOrderInfo, mchntOrderInfoList, mompPayOrderInfo);
            throw new BizException(RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
        } else if (!OpmsParamConstant.DUBBO_SUCCESS.equals(mompResponse.getRespCode())) {
            if (isCouponTrans) {
                rglog.error("使用卡劵交易调用营销失败,整个交易失败");
                updateOrderFail(userOrderInfo, mchntOrderInfoList, mompPayOrderInfo);
                throw new BizException(RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
            } else {
                mompPayOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                mompPayOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                mompPayOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                if (!orderService.updateOrderInfo(null, null, mompPayOrderInfo)) {
                    rglog.warn("更新用户订单/商户订单信息失败");
                }
                rglog.debug("交易调用营销失败但未使用卡劵可继续进行交易");
                /*d0实时入账手续费四舍五入处理*/
                if (AppParamConstant.YES.equals(mchntOrderInfoList.get(0).getRealSettleFlag())) {
                    for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                        mchntOrderInfo.setMchntDiscountFee("0.00");
                        mchntOrderInfo.setRealMchntFee(AmountUtil.rounding(mchntOrderInfo.getRealMchntFee(), 2));
                        mchntOrderInfo.setMchntFee(AmountUtil.rounding(mchntOrderInfo.getMchntFee(), 2));
                        mchntOrderInfo.setMchntSettleAmt(AmountUtil.subtraction(mchntOrderInfo.getRealSettleAmt(), mchntOrderInfo.getRealMchntFee()));
                    }
                }
            }
        } else {

            //判断是否使用营销 参与营销，不实时入账
            if (AmountUtil.compare(mompResponse.getTransAmt(), mompResponse.getTxnAmt()) != 0) {
                discountFlag = AppParamConstant.YES;
            }

            //更新用户订单实际支付金额和优惠金额
            userOrderInfo.setRealPayAmt(mompResponse.getTxnAmt());
            userOrderInfo.setRealDiscountAmt(AmountUtil.subtraction(userOrderInfo.getOrderAmt(), mompResponse.getTxnAmt()));
            if (null != cupsGatewayPayRequest.getCouponInfo() && null != cupsGatewayPayRequest.getCouponInfo().getDiscountId()) {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put(cupsGatewayPayRequest.getCouponInfo().getDiscountId(), cupsGatewayPayRequest.getCouponInfo().getDiscountAmt());
                userOrderInfo.setDiscountInfo(jsonObject.toJSONString());
            }

            List<PaymentOrderDetailBean> orderDetailBeanList = mompResponse.getOrderDetailList();
            if (orderDetailBeanList == null || orderDetailBeanList.isEmpty()) {
                rglog.error("营销返回数据有误");
                throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
            }

            //商户优惠金额计算
            for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                List<PaymentOrderDetailBean> paymentOrderDetailBeanList = orderDetailBeanList.stream().filter(item -> item.getMchntNo().equals(mchntOrderInfo.getMchntNo())).collect(Collectors.toList());
                if (paymentOrderDetailBeanList.isEmpty()) {
                    throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
                }

                /*用户优惠金额*/
                String moneyOffSubsidyTotal = "0.00";
                String couponTotalSubsidy = "0.00";
                if (paymentOrderDetailBeanList.get(0).getMoneyOffSubsidyTotal() != null) {
                    moneyOffSubsidyTotal = paymentOrderDetailBeanList.get(0).getMoneyOffSubsidyTotal();
                }
                if (paymentOrderDetailBeanList.get(0).getCouponTotalSubsidy() != null) {
                    couponTotalSubsidy = paymentOrderDetailBeanList.get(0).getCouponTotalSubsidy();
                }
                mchntOrderInfo.setCustomerMarketAmt(AmountUtil.addition(moneyOffSubsidyTotal, couponTotalSubsidy));

                /*商户手续费优惠金额*/
                String mchntFeeDiscount = mchntOrderInfo.getMchntDiscountFee();
                String mchntFeeActual = mchntOrderInfo.getRealMchntFee();
                if (paymentOrderDetailBeanList.get(0).getMchntFeeDiscount() != null && AmountUtil.compare(paymentOrderDetailBeanList.get(0).getMchntFeeDiscount(), "0") == 1) {
                    mchntFeeDiscount = paymentOrderDetailBeanList.get(0).getMchntFeeDiscount();
                    feeDiscountFlag = AppParamConstant.YES;
                }
                if (paymentOrderDetailBeanList.get(0).getMchntFeeActual() != null) {
                    mchntFeeActual = paymentOrderDetailBeanList.get(0).getMchntFeeActual();
                }
                /*实时清算时，实收手续费四舍五入处理*/
                if (AppParamConstant.YES.equals(mchntOrderInfo.getRealSettleFlag())) {
                    mchntFeeActual = AmountUtil.rounding(mchntFeeActual, 2);
                    if (mchntFeeDiscount == null || AmountUtil.compare(mchntFeeDiscount, "0") == 0) {
                        mchntFeeDiscount = "0.00";
                        mchntOrderInfo.setMchntFee(mchntFeeActual);
                    } else {
                        mchntFeeDiscount = AmountUtil.subtraction(mchntOrderInfo.getMchntFee(), mchntFeeActual);
                    }
                    mchntOrderInfo.setMchntDiscountFee(mchntFeeDiscount);

                } else {
                    mchntOrderInfo.setMchntDiscountFee(mchntFeeDiscount);

                }
                mchntOrderInfo.setRealMchntFee(mchntFeeActual);

                /*商户结算金额*/
                String channelDiscountAmt = "0.00";
                String mchntTotalSettleAmt = AmountUtil.subtraction(mchntOrderInfo.getRealSettleAmt(), mchntFeeActual);
                if ("0".equals(paymentOrderDetailBeanList.get(0).getMoneyOffSettlementMethod())) {
                    /*免充值需要减去商户满减补贴金额*/
                    mchntTotalSettleAmt = AmountUtil.subtraction(mchntTotalSettleAmt, paymentOrderDetailBeanList.get(0).getMoneyOffSubsidyMchnt());
                } else {
                    /*通道优惠金额累加*/
                    channelDiscountAmt = AmountUtil.addition(channelDiscountAmt, paymentOrderDetailBeanList.get(0).getMoneyOffSubsidyTotal());
                }
                if ("0".equals(paymentOrderDetailBeanList.get(0).getCouponMchntSettleMethod())) {
                    /*免充值需要减去商户卡券补贴金额*/
                    mchntTotalSettleAmt = AmountUtil.subtraction(mchntTotalSettleAmt, paymentOrderDetailBeanList.get(0).getCouponMchntSubsidy());
                } else {
                    /*通道优惠金额累加*/
                    channelDiscountAmt = AmountUtil.addition(channelDiscountAmt, paymentOrderDetailBeanList.get(0).getCouponTotalSubsidy());
                }
                mchntOrderInfo.setMchntSettleAmt(mchntTotalSettleAmt);
                mompPayOrderInfo.setChannelDiscountAmt(channelDiscountAmt);
                if (paymentOrderDetailBeanList.get(0).getCouponNo() != null) {
                    mchntOrderInfo.setRedeemCouponIds(paymentOrderDetailBeanList.get(0).getCouponNo());
                }
                mchntOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                //用户享受营销之后商户就不实时清算
                if (AppParamConstant.YES.equals(discountFlag)) {
                    rglog.info("当前用户享受营销,商户不支持实时清算");
                    mchntOrderInfo.setRealSettleFlag(OpmsParamConstant.OPMS_PARAM_NO);
                }
            }

            /*营销系统返回成功，更新订单支付订单状态为成功*/
            mompPayOrderInfo.setChannelDiscountAmt(mompResponse.getTotalSubsidy());
            mompPayOrderInfo.setSettleDate(DateUtil.getCurrentDate());
            mompPayOrderInfo.setRespDesc(mompResponse.getRespDesc());
            mompPayOrderInfo.setRespCode(mompResponse.getRespCode());
            mompPayOrderInfo.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
            mompPayOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
            mompPayOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            if (!orderService.updateOrderInfo(userOrderInfo, mchntOrderInfoList, mompPayOrderInfo)) {
                rglog.warn("更新营销支付订单表失败:<{}>", JSON.toJSONString(mompPayOrderInfo));
            }

            //是否使用优惠标识存入节点内
            if (AppParamConstant.NO.equals(discountFlag) && AppParamConstant.NO.equals(feeDiscountFlag)) {
                xmlTreeUtil.setXmlTreeStringValue("discountFlag", AppParamConstant.NO);
            } else {
                xmlTreeUtil.setXmlTreeStringValue("discountFlag", AppParamConstant.YES);
            }
        }
    }

    /**
     * 登记新网银支付订单表
     *
     * @param request       请求体
     * @param userOrderInfo 用户订单
     * @return 支付订单
     * @throws Exception 异常
     */
    private PayOrderInfo registPayOrderInfo(CupsGatewayPayRequest request, UserOrderInfo userOrderInfo) throws Exception {

        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);

        PayOrderInfo payOrderInfo = new PayOrderInfo();
        BeanUtil.beanCopy(userOrderInfo, payOrderInfo);
        payOrderInfo.setTxnDate(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_DATE));
        payOrderInfo.setTxnTime(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_TIME));
        payOrderInfo.setTxnNum(request.getHeader().getTxnNum());
        payOrderInfo.setBizType(request.getHeader().getBizType());
        payOrderInfo.setRealPayAmt(userOrderInfo.getRealPayAmt());
        payOrderInfo.setPayType(PayTypeEnum.OTHER_BANK_CARD.getPayType());
        payOrderInfo.setPayerAcctType("");
        payOrderInfo.setPayeeAcctType("");
        payOrderInfo.setPayeeAcctInfo("");
        payOrderInfo.setSysSeqNum(sysSeqNum);
        payOrderInfo.setMsgDstId(ChannelEnum.ESB.getChannelType());
        payOrderInfo.setDstCallIndex(OpmsParamConstant.STR_ZERO);
        payOrderInfo.setDstChannelType(ChannelEnum.UPGW.getChannelType());
        payOrderInfo.setDstTxnNum("");
        payOrderInfo.setChannelSeqNum(sysSeqNum);
        payOrderInfo.setChannelReconKey(sysSeqNum);
        payOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
        payOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        payOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        OrderService orderService = new OrderServiceImpl();
        if (!orderService.registerOrderInfo(null, null, payOrderInfo)) {
            rglog.error("登记支付订单表失败,payOrderInfo=[{}]", JSON.toJSONString(payOrderInfo));
            return null;
        } else {
            rglog.debug("登记支付订单表成功,payOrderInfo:<{}>", JSON.toJSONString(payOrderInfo));
        }
        return payOrderInfo;
    }

}
